#ifndef _H_C_TCP_SOCKET_IMPL_H_
#define _H_C_TCP_SOCKET_IMPL_H_

#include "../typedefine.h"
#include "ENetErrorCode.h"
#include "../coroutine.h"
#include <deque>
#include <memory>
#if _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#endif
#include "../coroutine.h"

namespace TB
{
	class CNetService;

	class CTcpSocketImpl
	{
		NON_COPYABLE(CTcpSocketImpl)
		NON_MOVEABLE(CTcpSocketImpl)

	private:
		struct SSendInfo
		{
			SSendInfo()
			{
			}
			SSendInfo(UINT32 dwBufferCount, STaskProcessor<ENetErrorCode>& oProcessor):
				m_sBuffer(dwBufferCount), m_oProcessor(oProcessor)
			{
			}
			std::vector<std::pair<UINT8*, UINT32>> m_sBuffer;
			STaskProcessor<ENetErrorCode> m_oProcessor;
			UINT32 m_dwToSendIndex = 0;
		};

		struct SRecvInfo
		{
			SRecvInfo()
			{
			}
			SRecvInfo(bool bIsRecvSome, const std::pair<UINT8*, UINT32>& sBuffer, STaskProcessor<std::pair<ENetErrorCode, UINT32>>& oProcessor) :
				m_bIsRecvSome(bIsRecvSome), m_sBuffer(sBuffer), m_oProcessor(oProcessor)
			{
			}

			bool m_bIsRecvSome = false;
			std::pair<UINT8*, UINT32> m_sBuffer;
			STaskProcessor<std::pair<ENetErrorCode, UINT32>> m_oProcessor;
			UINT32 m_dwRecvCount = 0;
		};

	public:
		CTcpSocketImpl(int nSocketFD);
		CTcpSocketImpl();
		~CTcpSocketImpl();
		inline std::weak_ptr<CNetService>& GetNetService() { return m_poNetService; }
		inline const std::weak_ptr<CNetService>& GetNetService() const { return m_poNetService; }
		bool Init(const std::weak_ptr<CNetService>& poNetService, const std::weak_ptr<CTcpSocketImpl>& poSelf);
		ENetErrorCode Bind(UINT32 dwIp, UINT16 wPort);
		void Connect(UINT32 dwIp, UINT16 wPort, UINT64 qwTimeoutMilliSeconds, STaskProcessor<ENetErrorCode>& sTaskProcessor); //主机字节序
		void Send(const std::pair<UINT8*, UINT32>& sBuffer, STaskProcessor<ENetErrorCode>& sTaskProcessor);
		void Send(const std::pair<UINT8*, UINT32>& sBuffer1, const std::pair<UINT8*, UINT32>& sBuffer2, STaskProcessor<ENetErrorCode>& sTaskProcessor);
		void Send(const std::pair<UINT8*, UINT32>& sBuffer1, const std::pair<UINT8*, UINT32>& sBuffer2, const std::pair<UINT8*, UINT32>& sBuffer3, STaskProcessor<ENetErrorCode>& sTaskProcessor);
		void Send(const std::pair<UINT8*, UINT32>* psBuffers, UINT32 dwCount, STaskProcessor<ENetErrorCode>& sTaskProcessor);
		void Recv(const std::pair<UINT8*, UINT32>& sBuffer, STaskProcessor<std::pair<ENetErrorCode, UINT32>>& sTaskProcessor);
		void RecvSome(const std::pair<UINT8*, UINT32>& sBuffer, STaskProcessor<std::pair<ENetErrorCode, UINT32>>& sTaskProcessor);
		void Close();
		bool IsClosed() const;
		bool IsConnecting() const;
		bool IsConnected() const;
		bool GetLocalIpPort(std::pair<UINT32, UINT16>& roIpPort) const;//主机字节序
		bool GetRemoteIpPort(std::pair<UINT32, UINT16>& roIpPort) const;//主机字节序
		bool SetNoDelay(bool bNoDelay = true);
		bool SetSendBuffer(UINT32 dwSize);
		bool SetRecvBuffer(UINT32 dwSize);

	private:
		void _Send();
		void _Recv();
		bool _AddPoll(bool bOut);
		bool _RemovePollOut();
		bool _RemovePollIn();

	private:
		std::weak_ptr<CNetService> m_poNetService;
		std::weak_ptr<CTcpSocketImpl> m_poSelf;
		STaskProcessor<ENetErrorCode> m_sConnectTask;
		ITimerContext::DStopTimer m_cbConnectTimeoutTimer;
		std::deque<SSendInfo> m_oSendTaskQueue;
		std::deque<SRecvInfo> m_oRecvTaskQueue;
#if _WIN32
		SOCKET m_nSocketFD = INVALID_SOCKET;
		INT16 m_nSettedEvents = 0;
#else
		int m_nSocketFD = -1;
		UINT32 m_nSettedEvents = 0;
#endif
	};
}

#endif